package com.example.tongyao.system.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.tongyao.common.SuperController;
import com.example.tongyao.system.entity.*;
import com.example.tongyao.system.message.SystemMessage;
import com.example.tongyao.system.service.*;
import com.example.tongyao.utils.DataResult;
import com.example.tongyao.utils.DateUtils;
import com.example.tongyao.utils.StringUtils;
import com.example.tongyao.utils.token.UserUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 角色表 前端控制器
 * </p>
 *
 * @author tongyao
 * @since 2021-08-18
 */
@RestController
@Api(tags = "系统_角色前端控制器")
@RequestMapping("/system/sys-role")
public class SysRoleController extends SuperController {

    @Resource
    private ISysRoleService iSysRoleService;

    @Resource
    private ISysUserRoleService iSysUserRoleService;

    @Resource
    private ISysRoleMenuService iSysRoleMenuService;

    @Resource
    private ISysInterfaceService iSysInterfaceService;

    @Resource
    private ISysRoleAuthService iSysRoleAuthService;


    /**
     * 分页查询所有角色
     * @return
     */
    @ApiOperation(
            value = "查询角色",
            notes = "分页查询所有角色",
            httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleName",value = "用户名称"),
            @ApiImplicitParam(name = "pageNo",value = "当前页数",defaultValue = "1"),
            @ApiImplicitParam(name = "pageSize",value = "显示条数",defaultValue = "10"),
            @ApiImplicitParam(name = "sortBy",value = "排序字段（多个以英文逗号拼接）",defaultValue = "create_time"),
            @ApiImplicitParam(name = "order",value = "排序类型",defaultValue = "asc")
    })
    @GetMapping(value = "/page" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult page(
            @RequestParam(required = false) String roleName,
            @RequestParam(defaultValue = "1") int pageNo,
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(defaultValue = "create_time") String sortBy,
            @RequestParam(defaultValue = "asc") String order) {

        LambdaQueryWrapper<SysRole> sysRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();

        if(StringUtils.isNotBlank(roleName)){
            sysRoleLambdaQueryWrapper.like(SysRole::getRoleName,roleName);
        }

        sysRoleLambdaQueryWrapper.eq(SysRole::getDelFlag,"1");
        sysRoleLambdaQueryWrapper.last(" order by "+sortBy+" "+order);

        Page<SysRole> page = new Page<>(pageNo,pageSize);
        IPage<SysRole> iPage = this.iSysRoleService.page(page,sysRoleLambdaQueryWrapper);
        return DataResult.setSuccess(iPage);
    }


    @ApiOperation(
            value = "增加角色",
            notes = "增加一个角色",
            httpMethod = "POST")
    @PostMapping(value = "/save" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult save(@Valid @RequestBody(required = true) SysRole sysRole) {

        codeExist(sysRole.getRoleCode());

        SysUser user = (SysUser) UserUtils.getUserInfo();

        sysRole.setDataScope("sys_all_data");
        sysRole.setRoleEnabled(true);
        sysRole.setDelFlag(1);
        sysRole.setCreateBy(user.getUserId());
        sysRole.setCreateTime(DateUtils.getDateTime());

        reuslt = iSysRoleService.save(sysRole);
        if(!reuslt){
            throw new RuntimeException(SystemMessage.user+SystemMessage.add+SystemMessage.fail+SystemMessage.a);
        }
        return DataResult.setSuccess(null);
    }

    //编辑一个角色
    @ApiOperation(
            value = "编辑角色",
            notes = "编辑一个角色，需根据roleId字段。",
            httpMethod = "PUT")
    @PutMapping(value = "/edit" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult edit(@Valid @RequestBody SysRole sysRole){

        SysUser user = (SysUser) UserUtils.getUserInfo();

        LambdaUpdateWrapper<SysRole> sysRoleLambdaUpdateWrapper = new LambdaUpdateWrapper<>();

        if(StringUtils.isNotBlank(sysRole.getRoleName())){
            sysRoleLambdaUpdateWrapper.set(SysRole::getRoleName,sysRole.getRoleName());
        }
        if(StringUtils.isNotBlank(sysRole.getRoleCode())){
            codeExist(sysRole.getRoleCode());
            sysRoleLambdaUpdateWrapper.set(SysRole::getRoleCode,sysRole.getRoleCode());
        }
        if(StringUtils.isNotBlank(sysRole.getRoleDesc())){
            sysRoleLambdaUpdateWrapper.set(SysRole::getRoleDesc,sysRole.getRoleDesc());
        }/*else if(StringUtils.isNotBlank(sysRole.getDataScope())){
            sysRoleLambdaUpdateWrapper.set(SysRole::getDataScope,sysRole.getDataScope());

        }*/

        if(StringUtils.isNotNull(sysRole.getSort())){
            sysRoleLambdaUpdateWrapper.set(SysRole::getSort,sysRole.getSort());
        }

        sysRoleLambdaUpdateWrapper.set(SysRole::getModifyBy,user.getUserId());
        sysRoleLambdaUpdateWrapper.set(SysRole::getModifyTime,DateUtils.getDateTime());

        sysRoleLambdaUpdateWrapper.eq(SysRole::getRoleId,sysRole.getRoleId());

        reuslt = iSysRoleService.update(sysRoleLambdaUpdateWrapper);
        if(!reuslt){
            throw new RuntimeException(
                    SystemMessage.role+
                    SystemMessage.update+
                    SystemMessage.fail+
                    SystemMessage.a);
        }
        return DataResult.setSuccess(null);
    }

    @ApiOperation(
            value = "删除角色",
            notes = "删除一个或多个角色",
            httpMethod = "DELETE")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId",value = "角色编号，多个以英文逗号拼接",required = true),
    })
    @DeleteMapping(value = "/delete" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult delete(@RequestParam String roleId){

        //从配置里获取默认角色
        SysConfig sysConfig = iSysConfigService.getConfigByKey("sys_default_role");
        if(StringUtils.isNull(sysConfig)){
            throw new RuntimeException("系统配置：${sys_default_role} 为空！");
        }

        map = commonService.getOne(
                "role_id",
                "sys_role",
                "role_code = '"+sysConfig.getConfigValue()+"' and del_flag = 1"
        );
        if(StringUtils.isNull(map)){
            throw new RuntimeException("属性值为：${"+sysConfig.getConfigValue()+"} 查询出来的数据为空！");
        }

        String mapRoleId = map.get("role_id").toString();
        if(mapRoleId.equals(roleId)){
            throw new RuntimeException("经系统设置，该角色不能删除！");
        }

        List roleIds = Arrays.asList(roleId.split(","));
        for (Object role: roleIds) {
            //校验是否删除默认角色
            if(!mapRoleId.equals(role)){

                //删除角色
                LambdaUpdateWrapper<SysRole> sysRoleLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                sysRoleLambdaUpdateWrapper
                        .set(SysRole::getDelFlag,"0")
                        .eq(SysRole::getRoleId,role);
                reuslt = iSysRoleService.update(sysRoleLambdaUpdateWrapper);
                if(!reuslt){
                    throw new RuntimeException(
                            SystemMessage.role+
                                    SystemMessage.delete+
                                    SystemMessage.fail+
                                    SystemMessage.a
                    );
                }
                //把用户角色关系角色字段替换成默认的
                LambdaUpdateWrapper<SysUserRole> sysUserRoleLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                sysUserRoleLambdaUpdateWrapper
                        .set(SysUserRole::getRoleId,mapRoleId)
                        .eq(SysUserRole::getRoleId,role);
                reuslt = iSysUserRoleService.update(sysUserRoleLambdaUpdateWrapper);
                if(!reuslt){
                    throw new RuntimeException(
                            SystemMessage.user+
                                    SystemMessage.role+
                                    SystemMessage.relation+
                                    SystemMessage.update+
                                    SystemMessage.fail+
                                    SystemMessage.a
                    );
                }

            }

        }

        return DataResult.setSuccess(null);
    }

    @ApiOperation(
            value = "更改状态",
            notes = "更改角色的启用禁用状态",
            httpMethod = "PUT")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId",value = "角色编号",required = true),
            @ApiImplicitParam(name = "state",value = "角色状态（true为启用，false为禁用）",required = true)
    })
    @PutMapping(value = "/changeState" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult changeState(
            @RequestParam String roleId,
            @RequestParam boolean state
    ){

        LambdaUpdateWrapper<SysRole> sysRoleLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        sysRoleLambdaUpdateWrapper
                .set(SysRole::isRoleEnabled,state)
                .eq(SysRole::getRoleId,roleId);
        reuslt = iSysRoleService.update(sysRoleLambdaUpdateWrapper);

        if(!reuslt){
            throw new RuntimeException(
                    SystemMessage.role +
                            SystemMessage.state+
                            SystemMessage.update +
                            SystemMessage.fail +
                            SystemMessage.a
            );
        }

        return DataResult.setSuccess(null);
    }

    @ApiOperation(
            value = "更改数据范围",
            notes = "更改角色的数据范围",
            httpMethod = "PUT")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId",value = "角色编号",required = true),
            @ApiImplicitParam(name = "dataScopeId",value = "数据权限字典id",required = true)
    })
    @PutMapping(value = "/changeDataScope" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult changeDataScope(
            @RequestParam String roleId,
            @RequestParam String dataScopeId
    ){

        LambdaUpdateWrapper<SysRole> sysRoleLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        sysRoleLambdaUpdateWrapper
                .set(SysRole::getDataScope,dataScopeId)
                .eq(SysRole::getRoleId,roleId);
        reuslt = iSysRoleService.update(sysRoleLambdaUpdateWrapper);

        if(!reuslt){
            throw new RuntimeException(
                    SystemMessage.role +
                            SystemMessage.dataScope+
                            SystemMessage.update +
                            SystemMessage.fail +
                            SystemMessage.a
            );
        }

        return DataResult.setSuccess(null);
    }

    //分配菜单
    @ApiOperation(
            value = "分配菜单",
            notes = "给角色分配菜单",
            httpMethod = "PUT")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId",value = "角色编号",required = true),
            @ApiImplicitParam(name = "menuId",value = "菜单编号，多个以英文逗号拼接",required = true)
    })
    @PutMapping(value = "/allotRMenu" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult allotRMenu(
            @RequestParam String roleId,
            @RequestParam String menuId
    ){
        //删除旧的角色菜单关系数据
        map = new HashMap();
        map.put("role_id",roleId);
        iSysRoleMenuService.removeByMap(map);

        List menuIds = Arrays.asList(menuId.split(","));
        SysRoleMenu sysRoleMenu = null;
        SysRoleAuth sysRoleAuth = null;
        for (Object menu: menuIds) {
            sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(menu.toString());
            sysRoleMenu.setRoleId(roleId);
            reuslt = iSysRoleMenuService.save(sysRoleMenu);
            if(!reuslt){
                throw new RuntimeException(
                        SystemMessage.menu +
                                SystemMessage.allot+
                                SystemMessage.fail +
                                SystemMessage.a
                );
            }

            map = new HashMap<>();
            map.put("menu_id",menu);
            List<SysInterface> sysInterfaceList = iSysInterfaceService.listByMap(map);
            for (SysInterface sysInterface: sysInterfaceList) {

                sysRoleAuth = new SysRoleAuth();
                sysRoleAuth.setInterfaceId(sysInterface.getInterfaceId());
                sysRoleAuth.setRoleId(roleId);
                reuslt = iSysRoleAuthService.save(sysRoleAuth);

                if(!reuslt){
                    throw new RuntimeException(
                            SystemMessage.role +
                                    SystemMessage.sysInterface+
                                    SystemMessage.add+
                                    SystemMessage.fail +
                                    SystemMessage.a
                    );
                }
            }

        }

        return DataResult.setSuccess(null);
    }

    @ApiOperation(
            value = "查询授权接口",
            notes = "查询配分菜单时，给该角色分配的接口地址",
            httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId",value = "角色编号",required = true)
    })
    @GetMapping(value = "/roleInterface" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult roleInterface(@RequestParam String roleId) {

        LambdaQueryWrapper<SysRoleAuth> sysRoleAuthLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysRoleAuthLambdaQueryWrapper.select(SysRoleAuth::getInterfaceId);
        sysRoleAuthLambdaQueryWrapper.eq(SysRoleAuth::getRoleId,roleId);
        List<SysRoleAuth> roleAuthList = iSysRoleAuthService.list(sysRoleAuthLambdaQueryWrapper);

        List<SysMenu> sysMenuList = iSysRoleService.getRoleInterfaceByRoleId(roleId);
        map = new HashMap<>();
        map.put("menu_interface",SysMenuController.showMenu(sysMenuList));
        map.put("checked_interface",roleAuthList);

        return DataResult.setSuccess(map);
    }


    //管理授权接口 待测试
    @ApiOperation(
            value = "更改菜单接口",
            notes = "删除旧的菜单接口，给该角色重新配置菜单接口。",
            httpMethod = "PUT")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId",value = "角色编号",required = true),
            @ApiImplicitParam(name = "interfaceId",value = "接口编号，多个以英文逗号拼接",required = true)
    })
    @PutMapping(value = "/changeRoleInterface" , produces = {MediaType.APPLICATION_JSON_VALUE})
    public DataResult changeRoleInterface(
            @RequestParam String roleId,
            @RequestParam String interfaceId
    ) {
        //删除所有旧接口
        map = new HashMap<>();
        map.put("role_id", roleId);
        iSysRoleAuthService.removeByMap(map);

        //新增所有新接口
        List interfaceIds = Arrays.asList(interfaceId.split(","));
        SysRoleAuth sysRoleAuth = null;
        for (Object sysInterface : interfaceIds) {

            sysRoleAuth = new SysRoleAuth();
            sysRoleAuth.setRoleId(roleId);
            sysRoleAuth.setInterfaceId(sysInterface.toString());
            reuslt = iSysRoleAuthService.save(sysRoleAuth);

            if (!reuslt) {
                throw new RuntimeException(
                        SystemMessage.role +
                                SystemMessage.sysInterface +
                                SystemMessage.add +
                                SystemMessage.fail +
                                SystemMessage.a
                );
            }
        }


        return DataResult.setSuccess(null);
    }


    /**
     * 判断角色编码是否存在
     * @param code
     * @return
     */
    public void codeExist(String code){
        int count = commonService.getCount("sys_role","role_code = '"+code+"' and del_flag = 1");
        if(count > 0){
            throw new RuntimeException(code+" 角色编码已存在！");
        }
    }
}
